package Thread;
import java.util.Comparator;
import java.util.PriorityQueue;
//通过这个类描述一个任务
class MyTimerTask implements Comparable<MyTimerTask> {
    //在什么时间点执行这个任务
    //约定为一个ms级别的时间戳
    //时间戳:以1970年1月1日0时0分0秒为基准以秒/毫秒/微秒计算时间戳
    private long time;
    private Runnable runnable;
    public long getTime(){
        return time;
    }

    //delay是一个相对的时间间隔
    public MyTimerTask( Runnable runnable , long delay) {
        this.time = delay + System.currentTimeMillis();
        this.runnable = runnable;
    }
    public void run (){
        runnable.run();
    }

    @Override
    public int compareTo(MyTimerTask o) {
        return (int)(this.time - o.time);
    }
}
//通过这个类表示定时器
class MyTimer{
    private PriorityQueue<MyTimerTask> queue = new PriorityQueue<>();
    //优先级队列需要先去指定比较规则. 实现Comparable Comparator接口
    private Thread t = null;
    private Object locker = new Object();
    public void schedule(Runnable runnable , long time) {
        synchronized (locker) {
            MyTimerTask myTimerTask = new MyTimerTask(runnable, time);
            queue.offer(myTimerTask);
            locker.notify();
        }
    }
    public void cancel(){
        t.interrupt();
    }

    //构造方法,创建扫描线程来完成判定和执行操作
    public MyTimer(){
        t = new Thread(() -> {
            //扫描线程就需要循环反复的扫描队首元素判断队首元素是否时间到了.
            //如果时间没到,什么也不干
            //如果时间到了,就取出元素.
            while(!t.isInterrupted()) {
                try {
                    synchronized (locker) {
                        while (queue.isEmpty()) {
                            locker.wait();
                        }
                        MyTimerTask task = queue.peek();
                        long currentTime = System.currentTimeMillis();
                        if (currentTime >= task.getTime()) {
                            //执行
                            queue.poll();
                            task.run();
                        } else {
                            //1.有新的任务出现wait会被唤醒,notify
                            //2.wait过程中没有新的任务,就按照原定时间计划执行
                            locker.wait(task.getTime() - currentTime);
                        }

                        //这里的代码执行很快.很可能导致其他线程抢不到锁,造成线程饿死.
                    }
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }

        });
        t.start();
    }
}
public class Test {
    public static void main(String[] args) throws InterruptedException {
        MyTimer myTimer = new MyTimer();
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("1000");
            }
        } , 3000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("3000");
            }
        } , 2000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("2000");
            }
        } , 1000);
        System.out.println(" hello man");
        Thread.sleep(5000);
        myTimer.cancel();
    }
}